﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.Spreadsheet;
using DevExpress.XtraBars.Docking2010.Views.WindowsUI;
using DevExpress.XtraSpreadsheet;
using DevExpress.XtraSpreadsheet.Menu;
using EduFormManager.Models;
using EduFormManager.Models.Repo;
using EduFormManager.Properties;
using EduFormManager.Utilities;
using DocumentFormat = DevExpress.Spreadsheet.DocumentFormat;

namespace EduFormManager.Forms.UserControls
{
    public partial class XtraDictionaryTemplateControl : XtraBaseControl, ISupportDocumentActions
    {
        public XtraDictionaryTemplateControl(WindowsUIView view)
            : base(view)
        {
            InitializeComponent();
        }

        public override IList<TemplatedFormData> DataSourceTemplatedFormData
        {
            set
            {
                templatedFormDataBindingSource.DataSource = value;
                UpdateData();
            }
        }
        public void New()
        {
            New(null);
        }
        protected override void New(Document doc)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.ShowDialog(this);
                if (String.IsNullOrEmpty(openFileDialog.FileName))
                {
                    return;
                }
                templatedFormDataBindingSource.AddNew();
                spreadsheetTemplate.LoadDocument(openFileDialog.FileName);
                spreadsheetTemplate.Document.History.IsEnabled = true;
                using (MemoryStream ms = new MemoryStream())
                {
                    spreadsheetTemplate.SaveDocument(ms, DocumentFormat.OpenXml);

                    byte[] data = ms.ToArray();
                    TemplatedFormData template = (TemplatedFormData)templatedFormDataBindingSource.Current;
                    Allform form = (Allform)comboBoxRemainingTemplatedForm.SelectedItem;

                    template.ExcelFileBytes = data;
                    template.AllForm = form;

                    if (form.CheckContents != null)
                    {
                        Encoding encoding = Encoding.UTF8; //Encoding.GetEncoding(checkData.CodePage);
                        string textContent = encoding.GetString(form.CheckContents ?? new byte[0]);
                        this.formulaEditControl1.Text = textContent;
                    }

                }
            }
        }
        public bool CanNew()
        {
            return CanNew(null);
        }
        protected override bool CanNew(Document doc)
        {
            return true;
        }
        public void Save()
        {
            Save(null);
        }
        protected override void Save(Document doc)
        {
            templatedFormDataBindingSource.EndEdit();
            ProgressDialog.ShowTop(this.ParentForm, description: "Сохраняю");

            TemplatedFormData template = (TemplatedFormData)templatedFormDataBindingSource.Current;
            Allform form = template.AllForm;

            template = SaveTemplateData(template);
            SaveCheckData(form);
            
            UpdateData();

            ProgressDialog.HideTop();   
        }

        private TemplatedFormData SaveTemplateData(TemplatedFormData template)
        {
            //if (template.Id == 0)
                return RepoHelper.Repo.SaveTemplate(template);
        }

        private void SaveCheckData(Allform form)
        {
            Encoding encoding = Encoding.UTF8;
            byte[] fileContents = encoding.GetBytes(this.formulaEditControl1.Text);
            string crc = FileUtility.GetCRC32AsHexString(fileContents);

            form.CheckContents = fileContents;
            form.CheckfileMD5 = crc;

            RepoHelper.Repo.SaveCheckData(form);
        }

        public bool CanSave()
        {
            return CanSave(null);
        }
        protected override bool CanSave(Document doc)
        {
            return templatedFormDataBindingSource.Current != null && spreadsheetTemplate.Document != null;
        }
        public void Remove()
        {
            Remove(null);
        }
        protected override void Remove(Document doc)
        {
            TemplatedFormData template = (TemplatedFormData)templatedFormDataBindingSource.Current;
            RepoHelper.Repo.Delete(template);
            templatedFormDataBindingSource.Remove(template);
            templatedFormDataBindingSource.EndEdit();

            UpdateData();
        }
        public bool CanRemove()
        {
            return CanRemove(null);
        }
        protected override bool CanRemove(Document doc)
        {
            return templatedFormDataBindingSource.Current != null;
        }

        protected override void UpdateData()
        {
            templatedFormDataBindingSource.DataSource = RepoHelper.Repo.GetAll<TemplatedFormData>();
            comboBoxRemainingTemplatedForm.DataSource = RepoHelper.Repo.GetRemainingFormsWithoutTemplate();
        }

        async private void listBoxTemplatedForm_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.formulaEditControl1.Text = string.Empty;
            TemplatedFormData template = (TemplatedFormData)templatedFormDataBindingSource.Current;
            if (template == null)
            {
                return;
            }
            byte[] excelData = template.ExcelFileBytes;
            if (excelData == null)
            {
                return;
            }
            using (MemoryStream ms = new MemoryStream(excelData))
            {
                DocumentFormat format = DocumentFormat.OpenXml;
                spreadsheetTemplate.LoadDocument(ms, format);
                spreadsheetTemplate.Document.History.IsEnabled = true;
            }
            Allform form = template.AllForm;
            byte[] checkData = form.CheckContents;
            this.layoutControl1.Enabled = false;
            if (checkData != null)
            {
                string textContent = await Task.Run<string>(() =>
                {
                    string crc = FileUtility.GetCRC32AsHexString(checkData);
                    Encoding encoding = Encoding.UTF8;
                    if (crc.Equals(form.CheckfileMD5))
                        return encoding.GetString(checkData);
                    return null;
                });
                if (textContent != null)
                {
                    this.formulaEditControl1.Text = textContent;
                }
                else
                {
                    this.formulaEditControl1.Text = string.Empty;
                    this.ShowFlyoutMessageBox("Ошибка загрузки формул", "Ошибка целостности данных", FlyoutCommand.OK);
                }
            }
            this.layoutControl1.Enabled = true;
        }

        public void OnQueryDocumentActions(IDocumentActionsArgs args)
        {
            args.DocumentActions.Add(new DocumentAction(New) { Caption = "Открыть файл", Image = Resources.glyphicons_144_folder_open });
            args.DocumentActions.Add(new DocumentAction(CanSave, Save) { Caption = "Сохранить", Image = Resources.glyphicons_206_ok_2 });
            args.DocumentActions.Add(new DocumentAction(CanRemove, Remove) { Caption = "Удалить", Image = Resources.glyphicons_207_remove_2 });
        }

        private void comboBoxRemainingTemplatedForm_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;
        }

        private void comboBoxRemainingTemplatedForm_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.listBoxTemplatedForm.ClearSelected();
            this.spreadsheetTemplate.CreateNewDocument();
            this.formulaEditControl1.Text = string.Empty;
        }

        private void spreadsheetTemplate_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e)
        {
            if (e.MenuType == SpreadsheetMenuType.Cell)
            {
                e.Menu.Items.Clear();
                IList<Range> ranges = this.spreadsheetTemplate.GetSelectedRanges();
                SpreadsheetMenuItem itemAddLeft         = new SpreadsheetMenuItem("Добавить cлева", (o, args) => this.formulaEditControl1.AddToLeftPart(ranges));
                SpreadsheetMenuItem itemReplaceLeft     = new SpreadsheetMenuItem("Заменить слева", (o, args) => this.formulaEditControl1.ReplaceLeftPart(ranges));
                SpreadsheetMenuItem itemAddRight        = new SpreadsheetMenuItem("Добавить справа", (o, args) => this.formulaEditControl1.AddToRightPart(ranges));
                SpreadsheetMenuItem itemReplaceRight    = new SpreadsheetMenuItem("Заменить справа", (o, args) => this.formulaEditControl1.ReplaceRightPart(ranges));

                itemAddLeft.BeginGroup = true;
                e.Menu.Items.Add(itemAddLeft);
                e.Menu.Items.Add(itemReplaceLeft);
                itemAddRight.BeginGroup = true;
                e.Menu.Items.Add(itemAddRight);
                e.Menu.Items.Add(itemReplaceRight);
            }
        }
    }
}
